package edu.uoc.tfc.exuoc.controladors;

import edu.uoc.tfc.exuoc.config.Config;

import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.HibernateException;

import edu.uoc.tfc.exuoc.model.Grup;
import edu.uoc.tfc.exuoc.errors.NoExisteixException;
import edu.uoc.tfc.exuoc.errors.BuitException;

import edu.uoc.tfc.exuoc.utils.Eines;
import edu.uoc.tfc.exuoc.utils.seguretat.InjeccioCodi;


/**
 * classe que contindrà totes les funcionalitats dels objectes Grup,
 * estableix la connexió amb l'objecte DAO per obtenir/enviar els objectes
 * de tipus Grup.
 * D'entrada aquest controlador només gestionarà les dades en forma de lectura
 * ja que no s'implementarà cap funcionalitat per guardar grups. Actua com si fos
 * una llista Enumeration.
 * 
 * @author Emili A. Moreno
 *
 */
public class GestorGrups {
    private static Integer numGrups=Config.valorNullInt;
    private grupsDAO dao= new grupsDAO();

    private GestorLogs  log=GestorLogs .getLogger(this.getClass().getName());
 
    public void obrir() throws HibernateException{
        if (this.dao==null) this.dao= new grupsDAO();
    }

    // Mètode que tancarà la sessió oberta un cop ja no calgui
    public void  tancar() throws HibernateException{
        try{
            dao.tancarConnexio();
            dao=null;
        }catch(HibernateException e){
            log.error("Hi ha hagut un error realitzant el tancament amb la base de dades ", e.getLocalizedMessage());
        }catch (NullPointerException e){
            this.log.info("Gestor Grups ja tancat");

        }

    }

    /** Modifica el grup indicat, actualment només es poden afegir/eliminar
     * usuaris als grups.
     * 
     * @param grup
     * @return Retorna un valor diferent de 0 si dóna un error
     * @throws HibernateException
     * @throws BuitException
     */
    public Long modificar(Grup grup) throws HibernateException, BuitException {
        Long falla=Config.valorNull;
        try {
            dao.modificar(grup);
            falla=0L;
        }catch (HibernateException e){
            falla=-3L;
            String[] cadError={grup.getNom(),String.valueOf(grup.getId())};
            log.error("No s'ha pogut modificar el grup :{}s. /n Amb id:{}", cadError);
            //throw e;
        }catch (BuitException e){
            falla=-31L;
            String[] cadError={grup.getNom(),String.valueOf(grup.getId())};
            log.error("No s'ha pogut modificar el grup :{}s. /n Amb id:{}", cadError);
            //throw e;
        }
        return falla;
    }

    public Grup llegir(Long id) throws NoExisteixException, HibernateException, BuitException{
        Grup  grup=null;
        grup=dao.consulta(id);

        if (grup==null){
            throw new NoExisteixException("No s'ha trobat el grup espcififcat amb id: "+id.toString(),this.getClass());
        }

        return grup;
    }

    public Grup llegir(String nomGrup) throws NoExisteixException, HibernateException, BuitException{
        Grup  grup=null;
        InjeccioCodi filtrar = new InjeccioCodi();
        try {
            grup = dao.consulta(filtrar.netejar(nomGrup));
        } catch (UnsupportedEncodingException ex) {
            log.error("Error filtrant el nom del grup");
            throw new NoExisteixException("No s'ha trobat el grup espcififcat amb id: "+nomGrup,this.getClass());
        }

        if (grup==null){
            throw new NoExisteixException("No s'ha trobat el grup espcififcat amb id: "+nomGrup,this.getClass());
        }

        return grup;
    }

  
    public Iterator<Grup> llistat() throws HibernateException, BuitException {

        return dao.llista();
    }
    public Iterator<Grup> llistat(int ini, int fi)throws HibernateException, BuitException {
        Iterator<Grup> llista=null;
        List<Grup> llistaAcotada=new ArrayList<Grup>();
        Grup grup=null;

        llista=this.llistat();
        for (int i=0; (i<=fi)&&(llista.hasNext());i++){
            grup=llista.next();
            if (ini<=i ) {
                llistaAcotada.add(grup);
            }

        }
        return llistaAcotada.iterator();
    }

    /**
     *
     * @param ordre
     * @param quants
     * @return
     * @throws HibernateException
     * @throws BuitException
     * Per futures implementacions de més funionalitats al gestor i per quan
     *  s'haig de fer un llistat paginat.
     */
    public Iterator<Grup> llistat(String ordre, int quants )
                    throws HibernateException, BuitException {

        Iterator<Grup> llistaAcotada;
        llistaAcotada=dao.llista(ordre, quants);
        return llistaAcotada;
    }

        /**
     *
     * @return Nombre d'usuaris del sistema
     */
    public int numGrups() throws HibernateException,BuitException{
        int nGrups=0;
        if (GestorGrups.numGrups.equals(Config.valorNullInt) ||
                (GestorGrups.numGrups <0)) {
            //Obtenim el número de grups
            try{
                nGrups=dao.quants();
                if (nGrups>0)  GestorGrups.numGrups=nGrups;
                else throw new BuitException("Classe Grup, count="+String.valueOf(nGrups));
            }catch (HibernateException e){
                    log.error("Falla la connexió amb la bddd. Error en conèixer el nombre de grups");
                    throw e ;
            }catch (BuitException e){
                    log.error("No hi ha grups");
                    throw e ;
            }
        }
        return GestorGrups.numGrups;
    }



    /*****************************************************
     *
     * TESTS
     * 
     *****************************************************/
    private void testNumGrups(GestorGrups gg){
        try {
            Eines.escriu("Num Grups abans de la inicialització static: "+gg.numGrups());
        } catch (HibernateException ex) {
            log.error("Error en obtenir el nombre de grups.", ex.getLocalizedMessage());
        } catch (BuitException ex) {
            log.error("nombre de grups incorrecte: ", ex.getLocalizedMessage());
        }

    }
    private void testllistaGrups(GestorGrups gg){

        try {
            Iterator<Grup> it=gg.llistat(Config.ORDRE, 6);
            Eines.escriu();
            Eines.escriu("Llista de grups:");
            while (it.hasNext()){
                Grup g=it.next();
                Eines.escriu(g);
            }
            long id=Config.ADIMINISTRADOR;
            Eines.escriu("Id grup:"+id+"    nom: "+gg.llegir(id).getNom());
        } catch (HibernateException ex) {
            log.error("Error en obtenir la llista de grups.", ex.getLocalizedMessage());
        } catch (BuitException ex) {
            log.error("llista buida de grups: ", ex.getLocalizedMessage());
        } catch (NoExisteixException ex) {
            log.error("llista buida de grup/s: ", ex.getLocalizedMessage());
        }

    }

   /**************************************
    * MAIN
    */


   public static void main(String args[]){
        GestorLogs  log= GestorLogs .getLogger(GestorGrups.class.getCanonicalName());
        GestorGrups gg=new GestorGrups();

        Eines.escriu("num Grups Variable static :"+GestorGrups.numGrups);
        gg.testNumGrups(gg);
        gg.testllistaGrups(gg);

        Grup grup=null;
        try {
            grup = gg.llegir(1L);
            Eines.escriu("Grup amb nom Gestor id: "+gg.llegir("gestor").getId());
        } catch (NoExisteixException ex) {
            Logger.getLogger(GestorGrups.class.getName()).log(Level.SEVERE, null, ex);
        } catch (HibernateException ex) {
            Logger.getLogger(GestorGrups.class.getName()).log(Level.SEVERE, null, ex);
        } catch (BuitException ex) {
            Logger.getLogger(GestorGrups.class.getName()).log(Level.SEVERE, null, ex);
        }
        Eines.escriu("Grup amb id 1: "+grup);
        gg.tancar();


    }



}
